﻿using System.Linq;
using Entities.DataBase;
using Modules.API;
using WebService.Service.Transfer;

namespace WebService.Service {

    public class CalculateServiceX : AbstractService, ICalculateServiceX {

        public SearchCurrencyResult GetExchangeRate(string passport, SearchCurrencyRequest request) {
            return Run(passport, token => Locate<ICurrencyExchangeService>().Search(request));
        }

        public CalculateResponse Calculate(string passport) {
            return Run(passport, token => {

                var userId       = token.UserId;
                var orders       = Locate<IOrderRepository>().GetAll();
                var orderRecords = Locate<IOrderRecordRepository>().GetAll();
                var stocks       = Locate<IPurchaseRecordRepository>().ListAllRecords();
                var costs        = Locate<ICostRepository>().List();

                var context = new CalculationContext {
                    UserID       = userId,
                    Orders       = orders,
                    OrderRecords = orderRecords,
                    Costs        = costs,
                    Purchases    = stocks
                };
                
                return new CalculateResponse {
                       TotalCost         = CalcTotalCost(context),
                       TotalOtherCost    = CalcOtherCost(context),
                       TotalPostage      = CalcTotalPostage(context),
                       TotalOrderPostage = CalcTotalOrderPostage(context),
                       TotalOrderPrice   = CalcTotalOrderPrice(context),
                       TotalOrderCost    = CalcTotalOrderCost(context),
                       AccountCost       = CalcAccountCost(context),
                       AccountPostage    = CalcAccountPostage(context)
                };
            });
        }

        private static double CalcTotalPostage(CalculationContext request) {
            return (double) request.Purchases.Sum(r => r.Postage * r.Count) 
                 + (double) request.Orders.Sum(t => t.OrderPostage);
        }

        private static double CalcTotalCost(CalculationContext request) {
            return (double) request.Purchases.Sum(r => r.Cost * r.Count);
        }

        private static double CalcOtherCost(CalculationContext request) {
            return (double) request.Costs.Sum(r => r.Amount);
        }

        private static double CalcTotalOrderCost(CalculationContext request) {
            return (double) request.OrderRecords.Sum(r => r.Cost * r.Count);
        }

        private static double CalcTotalOrderPostage(CalculationContext request) {
            return (double) request.Orders.Sum(r => r.TotalPostage);
        }

        private static double CalcTotalOrderPrice(CalculationContext request) {
            return (double) request.OrderRecords.Sum(r => r.Price * r.Count);
        }

        private static double CalcAccountCost(CalculationContext request) {
            return (double) request.Purchases.Where(p => p.OperatorId.Equals(request.UserID)).Sum(r => r.Cost * r.Count);
        }

        private static double CalcAccountPostage(CalculationContext request) {
            return    (double) request.Purchases.Where(p => p.PostOperatorId.Equals(request.UserID)).Sum(r => r.Postage * r.Count)
                    + (double) request.Orders.Where(o => o.OperatorId.Equals(request.UserID)).Sum(o => o.OrderPostage);
        }

    }
}
